/*
 * Programacao concorrente
 * Grupo-03a
 * Brenno Candido					7696500 
 * Jose Victor Uliana Martins		7656620
 * Maria Fernanda Garbim Avelino 	7277562
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
#include <limits.h>

#define N 1000000000
#define NTHREADS 100

pthread_mutex_t mutex;
unsigned int pts_in;

/** funcao para gerar numeros pseudo-randomicos **/
const unsigned int A = 1664525, C = 1013904223;
unsigned int next(unsigned int x) {
	return x*A+C;
}

/** funcao a ser rodada em thread  
	executando o metodo de monte carlo **/
void* monte_carlo(void *ptr) {
    unsigned int i, nthr, n;
    double x, y, rand;
	int pts = 0;
   
    rand = time(NULL);
    nthr = *(int*)ptr;
    n = N/NTHREADS;
    for(i=0; i<n; i++) {
        rand = next(rand);
        x = rand/UINT_MAX;
        rand = next(rand);
        y =rand/UINT_MAX;
        if(x*x + y*y <= 1) {
             pts++;
        }
    }
	
	pthread_mutex_lock(&mutex);
	pts_in += pts;
	pthread_mutex_unlock(&mutex);

	pthread_exit(NULL);
}


int main() {
    pthread_t thread[NTHREADS];
    int i, n;

    pts_in = 0;

    n = N/NTHREADS;
	//mutex = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutex_init(&mutex, NULL);

	// cria as threads
    for(i=0; i<NTHREADS; i++) {
		pthread_create(&thread[i], NULL, monte_carlo, &i);
    }
    
	// espera as threads acabarem
    for(i=0; i<NTHREADS; i++) {
		pthread_join(thread[i], NULL);
    }

    double pi = 4.0*pts_in/N;
    printf("%.6lf\n", pi);

    return 0;
}
